Skip to content

Commit

Permalink
FIR: Forbid sealed inline classes with primary constructors
Browse files Browse the repository at this point in the history
 #KT-27576
  • Loading branch information
ilmirus committed Jul 22, 2022
1 parent 57eda1c commit 4a87c9a
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE) { firDiagnostic ->
SealedInlineClassWithUnderlyingValueImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.SEALED_INLINE_CHILD_NOT_VALUE) { firDiagnostic ->
SealedInlineChildNotValueImpl(
firDiagnostic as KtPsiDiagnostic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ValueObjectNotSealedInlineChild::class
}

abstract class SealedInlineClassWithUnderlyingValue : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = SealedInlineClassWithUnderlyingValue::class
}

abstract class SealedInlineChildNotValue : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = SealedInlineChildNotValue::class
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,11 @@ internal class ValueObjectNotSealedInlineChildImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ValueObjectNotSealedInlineChild(), KtAbstractFirDiagnostic<KtDeclaration>

internal class SealedInlineClassWithUnderlyingValueImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.SealedInlineClassWithUnderlyingValue(), KtAbstractFirDiagnostic<KtDeclaration>

internal class SealedInlineChildNotValueImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
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_OBJECT_NOT_SEALED_INLINE_CHILD by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
val SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
val SEALED_INLINE_CHILD_NOT_VALUE by error<KtDeclaration>()
val SEALED_INLINE_CHILD_OVERLAPPING_TYPE by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ object FirErrors {
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_OBJECT_NOT_SEALED_INLINE_CHILD by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
val SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
val SEALED_INLINE_CHILD_NOT_VALUE by error0<KtDeclaration>()
val SEALED_INLINE_CHILD_OVERLAPPING_TYPE by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
}
}

if (declaration.modality == Modality.SEALED &&
context.languageVersionSettings.supportsFeature(LanguageFeature.SealedInlineClasses) &&
primaryConstructor?.source?.kind is KtRealSourceElementKind
) {
reporter.reportOn(declaration.source, FirErrors.SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE, context)
return
}

if (primaryConstructor == null) return

for ((name, primaryConstructorParameter) in primaryConstructorParametersByName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_INHERITOR_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_INHERITOR_IN_DIFFERENT_PACKAGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_INLINE_CHILD_NOT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_INLINE_CHILD_OVERLAPPING_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS
Expand Down Expand Up @@ -1241,6 +1242,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(VALUE_OBJECT_NOT_SEALED_INLINE_CHILD, "value object must be child of sealed inline class")
map.put(SEALED_INLINE_CHILD_NOT_VALUE, "child of sealed inline class must be value");
map.put(SEALED_INLINE_CHILD_OVERLAPPING_TYPE, "Sealed inline class child cannot be distinguished from another one");
map.put(SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE, "Sealed inline class cannot have underlying value");

// Inline
map.put(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ package kotlin.jvm
annotation class JvmInline

@JvmInline
sealed value class Result(val value: Any)
sealed <!SEALED_INLINE_CLASS_WITH_UNDERLYING_VALUE!>value<!> class Result(val value: Any)

0 comments on commit 4a87c9a

Please sign in to comment.